package com.giant.services;

import com.giant.exceptions.OperacionInvalidaException;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Harold
 */
@Stateless
public class ServicioPersistencia implements IServicioPersistenciaLocal, Serializable {

    //-----------------------------------------------------------
    // Atributos
    //-----------------------------------------------------------
    /**
     * La entidad encargada de persistir en la base de datos
     */
    @PersistenceContext
    private EntityManager entityManager;

    //-----------------------------------------------------------
    // Constructor
    //-----------------------------------------------------------
    /**
     * Constructor de la clase. Inicializa los atributos.
     */
    public ServicioPersistencia() {
    }

    //-----------------------------------------------------------
    // Métodos
    //-----------------------------------------------------------
    /**
     * Permite crear un objeto dentro de la persistencia del sistema.
     * @param obj Objeto que representa la instancia de la entidad que se quiere
     * crear.
     */
    @Override
    public void create(Object obj) throws OperacionInvalidaException {
        entityManager.persist(obj);
    }

    /**
     * Permite modificar un objeto dentro de la persistencia del sistema
     * @param obj Objeto que representa la instancia de la entidad que se quiere
     * modificar.
     */
    @Override
    public void update(Object obj) {
        entityManager.merge(obj);
    }

    /**
     * Permite borrar un objeto dentro de la persistencia del sistema.
     * @param obj Objeto que representa la instancia de la entidad que se quiere
     * borrar.
     */
    @Override
    public void delete(Object obj) throws OperacionInvalidaException {
        entityManager.remove(obj);
    }

    /**
     * Retorna la lista de todos los elementos de una clase dada que se
     * encuentran en el sistema.
     * @param c Clase cuyos objetos quieren encontrarse en el sistema.
     * @return list Listado de todos los objetos de una clase dada que se
     * encuentran en el sistema.
     */
    @Override
    public List findAll(Class c) {
        return entityManager.createQuery("select O from " + c.getSimpleName() + " as O").getResultList();
    }

    /**
     * Retorna la instancia de una entidad dado un identificador y la clase de
     * la entidad
     * @param c Clase de la instancia que se quiere buscar.
     * @param id Identificador unico del objeto.
     * @return obj Resultado de la consulta.
     */
    @Override
    public Object findById(Class c, Object id) {
        return null;
    }

    /**
     * Ejecuta sql por objetos y permite ingreso de parámetros
     * @param a
     * @param map
     * @return
     */
    @Override
    public List executeSql(String a, Map<String, String> map) {
        System.out.println("Query: " + a);
        Query temp = entityManager.createNamedQuery(a);
        if (map != null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                System.out.println("[" + key + "]->" + value);
                try {
                    int var = Integer.parseInt(value);
                    temp.setParameter(key, var);
                } catch (Exception e) {
                    temp.setParameter(key, value);
                }
            }
        }
        System.out.println("Query results:" + temp.getResultList().size());
        return temp.getResultList();
    }
    /**
     * Ejecuta codigo sql generico
     * @param sql
     * @return 
     */
    @Override
    public List executeGenericSQL(String sql) {
        return entityManager.createNativeQuery(sql).getResultList();
    }

    /**
     * Ejecuta sql generico, no obstante serializa el resulta de la consulta,
     * volviendolo un objeto
     * @param sql
     * @param e
     * @return
     */
    @Override
    public List executeGenericSQLSerialized(String sql, Class e) {
        System.out.println(sql);
        return entityManager.createNativeQuery(sql, e).getResultList();
    }

    /**
     * Ejecuta sql generico para consultas de tipo insert, update o delete
     * @param sql
     */
    @Override
    public void executeGenericSQLAdd(String sql) {
        System.out.println(sql);
        entityManager.createNativeQuery(sql).executeUpdate();

    }

    /**
     * Ejecuta SQL por objetos
     * @param query
     * @return
     */
    @Override
    public List executeObjectSql(String query) {
        return entityManager.createQuery(query).getResultList();
    }
}
